- Bioconductor (Durinck et al.
(2009))
- R language (R Core Team (2022))
- Article (Adams et al. (2019))
- Rmarkdown (Allaire et al. (2021))
- edgeR (Robinson, DJ, and Smyth
(2010))
- GEOquery (Davis and Meltzer
(2007))
- SHH (Magliano et al. (2006))
- Limma (Ritchie et al. (2015))
- ComplexHeatMap (Gu (2022))
- Circlize (Gu et al. (2014))
Installing Dependencies
if (!requireNamespace("BiocManager", quietly = TRUE)){
install.packages("BiocManager")}
if (!requireNamespace("edgeR", quietly = TRUE)){
BiocManager::install("edgeR")}
if (!requireNamespace("GEOquery", quietly = TRUE)){
BiocManager::install("GEOquery")}
if (!requireNamespace("ComplexHeatmap", quietly = TRUE)){
BiocManager::install("ComplexHeatmap")}
if (!requireNamespace("limma", quietly = TRUE)){
BiocManager::install("limma")}
if (!requireNamespace("ExpressionSet", quietly = TRUE)){
BiocManager::install("ExpressionSet")}
Update all/some/none? [a/s/n]:
n
if (!requireNamespace("circlize", quietly = TRUE)){
BiocManager::install("circlize")}
if (!requireNamespace("gprofiler2", quietly = TRUE))
BiocManager::install("gprofiler2")
if (!requireNamespace("kableExtra", quietly = TRUE))
BiocManager::install("kableExtra")
if (!requireNamespace("plotly", quietly = TRUE))
BiocManager::install("plotly")
if (!requireNamespace("dplyr", quietly = TRUE))
BiocManager::install("dplyr")
library(dplyr)
library(plotly)
Part 1: Loading the normalized gene data
The normalized data has already been written into a text file by the
previous Assignment 1. For better assessment, I have indicated it on the
file uploaded.
normalized_count_data <- read.table(file=file.path(getwd(), "normalized_counts_annotated")
, header = TRUE, stringsAsFactors = FALSE, check.names = FALSE )
knitr::kable(normalized_count_data[1:10,1:7], type="pipe")
|
hgnc_symbol
|
YRE1A
|
YRE1B
|
YRE2A
|
YRG1A
|
YRG1B
|
YRG2B
|
|
A4GALT
|
4.345648
|
3.111477
|
2.408097
|
5.369569
|
6.397003
|
6.796014
|
|
AAAS
|
19.317681
|
22.327817
|
21.792253
|
18.384756
|
17.419577
|
17.311220
|
|
AACS
|
32.913059
|
24.534108
|
24.466495
|
23.731644
|
17.621289
|
17.428989
|
|
AADACP1
|
2.418554
|
4.507231
|
3.916687
|
13.734990
|
14.270060
|
14.143042
|
|
AADAT
|
4.058510
|
3.995899
|
3.647402
|
4.637361
|
4.052613
|
3.678086
|
|
AAED1
|
14.351471
|
11.913866
|
12.242066
|
12.711562
|
8.425186
|
7.790737
|
|
AAGAB
|
36.922469
|
35.816951
|
39.338927
|
40.358329
|
31.836730
|
30.961949
|
|
AAK1
|
1.531217
|
1.364910
|
1.534162
|
2.165459
|
2.677295
|
2.667404
|
|
AAMDC
|
46.807715
|
44.246410
|
48.924065
|
66.090858
|
49.702345
|
44.178113
|
|
AAMP
|
82.175802
|
88.352333
|
93.832788
|
76.203567
|
81.078221
|
82.443384
|
Part 2: Defining Portions of the Heatmap Matrix
I am defining the elements of the normalized data matrix which I will
be using for the heatmap later.
Part 3: Creating Heatmap
The heatmap uses different colors for the expression data. The
heatmap has many genes clustered based on their expression at different
levels such as control (EA1,EA2,EB1) or the cells treated with GLI2
(G1A,G2A,G1B).
if(min(heatmap_matrix) == 0){
heatmap_col = circlize::colorRamp2(c( 0, max(heatmap_matrix)),
c("white", "purple"))
} else {
heatmap_col = circlize::colorRamp2(c(min(heatmap_matrix), 0,
max(heatmap_matrix)), c("darkgreen", "white", "purple"))
}
first_heatmap <- ComplexHeatmap::Heatmap(as.matrix(heatmap_matrix),
show_row_dend = TRUE, show_column_dend = TRUE,
col=heatmap_col, show_column_names = TRUE,
show_row_names = FALSE, show_heatmap_legend = TRUE)
first_heatmap

Part 4: SPP1 EMT Genes-Conclusion justification
SPP1 is an EMT genes It shows higher expression when treated with
GLI2 compare to empty vector control cells (EV). This has been also
proved by the authors. However, indicating this again would strengthen
the hypothesis corresponding to Dox treated cells having GLI2 vector
show higher EMT gene expression as opposed to controls having empty
vector showing less expression of the genes.
GLI2_treatment_samples <- grep(colnames(normalized_count_data),pattern = "\\G")
EV_tratment_samples <- grep(colnames(normalized_count_data),pattern = "\\E")
gene_of_interest <- which(normalized_count_data$Gene_symbol == "SPP1")
YAPC_GLI2_samples <- t(normalized_count_data[gene_of_interest,5:7])
colnames(YAPC_GLI2_samples) <- c("GLI2_vector_cells")
YAPC_EV_samples <- t(normalized_count_data[gene_of_interest,2:4])
colnames(YAPC_EV_samples) <- c("Empty_Vector_cells")
YAPC_GLI2_samples
GLI2_vector_cells
YRG1A 321.9614
YRG1B 607.5096
YRG2B 580.2982
YAPC_EV_samples
Empty_Vector_cells
YRE1A 1.307170
YRE1B 1.616595
YRE2A 1.752119
Part 5: T-test between EV and GLI2
GLI2 treated cells are different in terms of their expression from
the empty vector cells. P value (0.03135) < 0.05. Indeed this shows
there is significant difference. However, this requires to see if GLI2
treatments show difference among one another so the control cells.
t.test(x=t(YAPC_GLI2_samples), y=t(YAPC_EV_samples))
Welch Two Sample t-test
data: t(YAPC_GLI2_samples) and t(YAPC_EV_samples)
t = 5.5139, df = 2, p-value = 0.03135
alternative hypothesis: true difference in means is not equal to 0
95 percent confidence interval:
110.2125 893.1831
sample estimates:
mean of x mean of y
503.256412 1.558628
PART 6: MDS Plot for Sample Clustering
The MDS plot allowed to visualize the difference within the different
cell types Earlier examples of MDS plot showed similar results. I
hypothesize that GLI2 expression is higher than control cell’s
expression levels due to DOX induction of EMT genes. In general I have
observed Gli2 cells to be less clustered, due to higher differential
expression among GLI2 cells.
limma::plotMDS(heatmap_matrix,col=c(rep("darkgreen",3), rep("blue",3)))

Part 7: Model Building of GLI2 expression status
The model I am building is based upon GLI2 expression status of genes
that are showing higher expression with significant indications of the
differential expression.
samples <- data.frame(lapply(colnames(normalized_count_data)[2:7],
FUN=function(x){unlist(strsplit(x, split = "[0-9]"))[c(1)]}))
colnames(samples) <- colnames(colnames(normalized_count_data)[2:7])
rownames(samples) <- c("Treatments")
samples <- data.frame(t(samples))
knitr::kable(samples, type = "pipe")
|
Treatments
|
|
YRE
|
|
YRE
|
|
YRE
|
|
YRG
|
|
YRG
|
|
YRG
|
YRG_model <- model.matrix( ~ samples$Treatments)
knitr::kable(YRG_model[1:6,], type = "pipe")
|
(Intercept)
|
samples$TreatmentsYRG
|
|
1
|
0
|
|
1
|
0
|
|
1
|
0
|
|
1
|
1
|
|
1
|
1
|
|
1
|
1
|
Part 8: Model Fitting and Differential Expression Calculation
The differential expression data matrix corresponding to gene symbols
were merged with the matrix that has the fitted model. The
Benjamin-hochberg correction method was applied to adjust the expression
data.
expressionMatrix <- as.matrix(normalized_count_data[,2:7])
rownames(expressionMatrix) <- normalized_count_data$Gene_symbol
colnames(expressionMatrix) <- colnames(normalized_count_data)[2:7]
set_expression_matrix <- Biobase::ExpressionSet(assayData = expressionMatrix)
fit <- limma::lmFit(set_expression_matrix, YRG_model)
fit_Bayes <- limma::eBayes(fit, trend = TRUE)
BH_method_fit <- limma::topTable(fit_Bayes,
coef = ncol(YRG_model),
adjust.method = "BH",
number = nrow(expressionMatrix))
merged_hits <- merge(normalized_count_data$Gene_symbol,
BH_method_fit,
by.y=0,by.x=1,
all.y=TRUE)
merged_hits <- merged_hits[order(merged_hits$P.Value),]
colnames(merged_hits) <- c("Gene_symbol","logFC", "AveExpr", "t",
"P.Value","adj.P.Val", "B")
rownames(merged_hits) <- 1:nrow(merged_hits)
knitr::kable(merged_hits[1:10,1:7], type = "pipe", row.names = FALSE,)
|
Gene_symbol
|
logFC
|
AveExpr
|
t
|
P.Value
|
adj.P.Val
|
B
|
|
S100A2
|
192.67873
|
105.164286
|
63.79569
|
0e+00
|
0.0000245
|
1.820600
|
|
SSFA2
|
76.45805
|
75.591839
|
45.17567
|
0e+00
|
0.0000789
|
1.781362
|
|
NT5E
|
86.27685
|
123.407858
|
42.93449
|
0e+00
|
0.0000789
|
1.773004
|
|
S100A13
|
132.80964
|
179.285328
|
37.98876
|
0e+00
|
0.0001191
|
1.749192
|
|
TRIB2
|
51.68968
|
38.062060
|
35.69100
|
1e-07
|
0.0001361
|
1.734718
|
|
HEG1
|
-13.44713
|
8.317468
|
-31.24508
|
1e-07
|
0.0002423
|
1.697467
|
|
NTN4
|
35.83705
|
33.048568
|
28.42566
|
2e-07
|
0.0003561
|
1.664696
|
|
UCP2
|
80.78518
|
94.331418
|
26.66241
|
3e-07
|
0.0004488
|
1.638993
|
|
PLLP
|
-31.42241
|
35.188668
|
-25.42904
|
4e-07
|
0.0004683
|
1.617932
|
|
UNC5B
|
19.59576
|
12.041479
|
24.78963
|
5e-07
|
0.0004683
|
1.605831
|
Part 9: P-value Assessment
The p-value was adjusted to have more stringent results. Normally
significant p-value is set to 0.05. However, I wanted to be more
stringent on my results and indicate the specific EMT genes. Probable
genes are 741. However, there are 27 genes that have significant
potential to be an EMT gene.
length(which(merged_hits$P.Value < 0.0005))
[1] 741
length(which(merged_hits$adj.P.Val < 0.0005))
[1] 27
Part 10: Model Visualization
This part of this assignment aims to detect SPP1’s role on how GLI2
cells are more differently expressed and do have higher difference than
the control cells. It is evident that, with more stringent p-value, the
significant portion (741) of about 11500 genes are showing features of
EMT genes
model_pvalues <- data.frame(Gene_symbol = merged_hits$Gene_symbol,
pvalue = merged_hits$P.Value)
model_pvalues$color <- "black"
model_pvalues$color[model_pvalues$pvalue < 0.0005] <- "orange"
SPP1 <- normalized_count_data$Gene_symbol[which(normalized_count_data$Gene_symbol == "SPP1")]
model_pvalues$color[model_pvalues$Gene_symbol== SPP1] <- "red"
plot(model_pvalues$pvalue,
col = model_pvalues$color,
xlab = "Number of Genes within the Dataset",
ylab ="P-value",
main="P value distribution of EMT Genes")
points(model_pvalues[which(model_pvalues$Gene_symbol == "SPP1"), 1:2],
pch = 20, col="red", cex=1.5)
legend(0, 1, legend=c("SPP1"), fill=c("red"))

Part 11: Clustered Heatmap with More Stringent Values
With more stringent gene size I was able to see cleaner difference
between GLI2 and the control cells. The clustered genes are the
symmetric each other across the diagonals. The high expression showing
genes on the GLI2’s side is lower on the EV’ side. Top hits are assessed
on the stringent p-value of 0.0005. The difference between the first and
the latest heatmap shows there is significant difference in terms of
gene expression whose expression is represented for each respective
Treatments
top_hits <- merged_hits$Gene_symbol[merged_hits$P.Value < 0.0005]
heatmap_matrix_tophits <- t(scale(t(heatmap_matrix[which(rownames(heatmap_matrix)
%in% top_hits),])))
if(min(heatmap_matrix_tophits) == 0){
heatmap_col = circlize::colorRamp2(c( 0, max(heatmap_matrix_tophits)),
c( "white", "purple"))
} else{
heatmap_col = circlize::colorRamp2(c(min(heatmap_matrix_tophits), 0,
max(heatmap_matrix_tophits)), c("darkgreen", "white", "purple"))
}
latest_heatmap <- ComplexHeatmap::Heatmap(as.matrix(heatmap_matrix_tophits),
show_row_dend = TRUE, show_column_dend = TRUE, col=heatmap_col,
show_column_names = TRUE, show_row_names = FALSE, show_heatmap_legend = TRUE)
latest_heatmap

first_heatmap

Part 12: Dataset Filtering and Data Extracting
The previously extracted GSE131222 data from gene omnibus expression
(GEO) is extracted separately. The low count portions of the data
filtered and a new matrix was created.
data = GEOquery::getGEOSuppFiles("GSE131222")
trying URL 'https://ftp.ncbi.nlm.nih.gov/geo/series/GSE131nnn/GSE131222/suppl//GSE131222_YAPCrtta-EV_GLI2_Adams.txt.gz?tool=geoquery'
Content type 'application/x-gzip' length 875595 bytes (855 KB)
downloaded 855 KB
datanames = rownames(data)
GLI2_exp =read.delim(datanames[1],header=TRUE,check.names = FALSE)
count_per_ms = edgeR::cpm(GLI2_exp[,3:8])
rownames(count_per_ms) <- GLI2_exp[,2]
rows_filtered = rowSums(count_per_ms >1) >= 6
GLI2_exp_filtered = GLI2_exp[rows_filtered,]
filtered_GLI2_matrix <- as.matrix(GLI2_exp_filtered[,3:8])
rownames(filtered_GLI2_matrix) <- GLI2_exp_filtered$gene
head(GLI2_exp_filtered)[1:8]
Part 13: Grouping Based on the Cell Types
The similar grouping was done previously. However this time
dispersion values, normalization factors and differential expression
model fitting is applied to the samples of GLI2 treatments.
grouped_treatments <- data.frame(lapply(colnames(GLI2_exp_filtered)[3:8],
FUN=function(x){unlist(strsplit(x, split = "[0-9]"))[c(1)]}))
colnames(grouped_treatments) <- colnames(GLI2_exp)[3:8]
rownames(grouped_treatments) <- c("cell_type")
grouped_treatments_normalized <- data.frame(t(grouped_treatments))
d = edgeR::DGEList(counts=filtered_GLI2_matrix, group = grouped_treatments_normalized$cell_type)
model_design_celltypes <- model.matrix(~grouped_treatments_normalized$cell_type+0)
d <- edgeR::estimateDisp(d, model_design_celltypes)
d <- edgeR::calcNormFactors(d)
fit <- edgeR::glmQLFit(d, model_design_celltypes)
qlf_test.GLI2vsEV <- edgeR::glmQLFTest(fit, coef = "grouped_treatments_normalized$cell_typeYRG")
Part 14: Significant Results within the Fitted Model
With more stringent p-value I was able to assess the critical
threshold for the expression threshold. I set the p-value as 0.0005. I
decided to put it by adjusting and observing any difference. The
difference between p-value 0.005 and p-value 0.0005 is one. This means
this p-value is safe to assume as a threshold for significance among
these differentially expressing genes.
qlf_top_hits <- edgeR::topTags(qlf_test.GLI2vsEV,sort.by = "PValue", n = nrow(filtered_GLI2_matrix))
head(qlf_top_hits)
Coefficient: grouped_treatments_normalized$cell_typeYRG
length(which(qlf_top_hits$table$PValue < 0.0005))
[1] 2434
length(which(qlf_top_hits$table$FDR < 0.0005))
[1] 2433
length(which(qlf_top_hits$table$logFC < 0))
[1] 11527
Part 15: Thresholded Gene List and Final EMT Gene Detection
The threshold was calculated and based its value I assessed the how
many genes actually show traits similar to GLI2. I used P value 1 to
eliminate significant portion of the differentially expressed genes. I
did not use the LogFC to distinguish between EMT GLI2 vs non-EMT GLI2,
because all of logFC values are negative. This indicates there is always
up regulation after the Dox treatment and GLI2 expression is always
higher than the control. Pretty high confidence.
qlf_tophits_withgn <- merge(GLI2_exp[,1:1], qlf_top_hits, by.y=0,by.x=1,all.y=TRUE)
colnames(qlf_tophits_withgn) <- c("Gene_symbol", "logFC", "logCPM","F", "PValue", "FDR")
qlf_tophits_withgn[,"logarithmic"] <- (-log(qlf_tophits_withgn$PValue))
qlf_tophits_withgn <- qlf_tophits_withgn[order(qlf_tophits_withgn$Gene_symbol),]
GLI2_emt_Genes <- qlf_tophits_withgn$Gene_symbol[which(qlf_tophits_withgn$PValue < 0.0005
& qlf_tophits_withgn$logFC < 0)]
GLI2_non_emtgenes <- qlf_tophits_withgn$Gene_symbol[which(qlf_tophits_withgn$PValue == 1)]
write.table(x=GLI2_emt_Genes, file = file.path(getwd(),"data","GLI2_emt_Genes.txt"),
sep = "/", row.names = FALSE, col.names = FALSE, quote = FALSE)
write.table(x=GLI2_non_emtgenes, file = file.path(getwd(),"data","GLI2_non_emtgenes.txt"),
sep = "/", row.names = FALSE, col.names = FALSE, quote = FALSE)
write.table(x=data.frame(genename=qlf_tophits_withgn$Gene_symbol[18:nrow(qlf_tophits_withgn)]),file=file.path("data","ranked_genelist.rnk"),sep = "/",
row.names = FALSE,col.names = FALSE,quote = FALSE)
Part 16: GProfiler for Upregulation and Downregulation pathway
analysis
The GProfiler analysis includes BH correction methods (FDR). I
sticked using the same method because I used the same type of method on
my previous analysis on FDR portion. For both upregualted and the
downregulated genes I have used GO:BP
(2022-12-04), Reactome, and WikiPathways( for annotation. These
annotations allows for better asessment of my Upregualted genes in terms
of defining the biologic pathways they are invovled in.
Upregulated_genes <- read.table(file=file.path(getwd(),"data" ,"GLI2_emt_Genes.txt"),header = TRUE, stringsAsFactors = FALSE, check.names = FALSE)
Upregulated_genes <- Upregulated_genes[4:nrow(Upregulated_genes),]
Upregulated_Gprofiler_validated <- gprofiler2::gost(query = Upregulated_genes,
organism = "hsapiens",
exclude_iea = TRUE,
sources = c("GO:BP", "REAC", "WP"),
correction_method = "fdr",
ordered_quer = FALSE,
)
Continuing Analysis
Downregulated_genes <- read.table(file=file.path(getwd(),"data" ,"GLI2_non_emtgenes.txt"),header = TRUE, stringsAsFactors = FALSE, check.names = FALSE)
Downregulated_genes <- Downregulated_genes[13:nrow(Downregulated_genes),]
Downregulated_Gprofiler_validated <- gprofiler2::gost(query = Downregulated_genes,
organism = "hsapiens",
exclude_iea = TRUE,
correction_method = "fdr",
ordered_quer = FALSE,
source = c("GO:BP", "REAC", "WP"))
Part 17: Subsetting the Gprofiler downregulated and upregualted
genes
After subsetting I do have 771 genes that are down regulated. Down
regualted genes are invovled in common biological pathways that are not
involved in cancerous activities.
Downregulated_genes_filtered <- data.frame(
term_name = Downregulated_Gprofiler_validated$result$term_name[Downregulated_Gprofiler_validated$result$term_size < 200 & Downregulated_Gprofiler_validated$result$term_size > 1],
term_id = Downregulated_Gprofiler_validated$result$term_id[Downregulated_Gprofiler_validated$result$term_size < 200 &
Downregulated_Gprofiler_validated$result$term_size > 1],
source = Downregulated_Gprofiler_validated$result$source[Downregulated_Gprofiler_validated$result$term_size < 200 &
Downregulated_Gprofiler_validated$result$term_size > 1]
)
length(Downregulated_genes_filtered$term_name)
[1] 771
knitr::kable(Downregulated_genes_filtered$term_name[1:50], format = "html")
|
x
|
|
tRNA metabolic process
|
|
cell cycle checkpoint signaling
|
|
DNA-templated transcription elongation
|
|
tRNA processing
|
|
regulation of DNA-templated transcription elongation
|
|
DNA-templated DNA replication
|
|
DNA integrity checkpoint signaling
|
|
tRNA modification
|
|
regulation of transcription elongation by RNA polymerase II
|
|
transcription elongation by RNA polymerase II
|
|
RNA modification
|
|
negative regulation of mitotic cell cycle
|
|
DNA damage checkpoint signaling
|
|
phosphatidylinositol biosynthetic process
|
|
signal transduction in response to DNA damage
|
|
mitotic cell cycle checkpoint signaling
|
|
protein acetylation
|
|
peptidyl-lysine acetylation
|
|
glycerophospholipid biosynthetic process
|
|
phosphatidylinositol metabolic process
|
|
negative regulation of mitotic cell cycle phase transition
|
|
histone acetylation
|
|
positive regulation of transcription elongation by RNA polymerase II
|
|
rRNA processing
|
|
internal peptidyl-lysine acetylation
|
|
microtubule organizing center organization
|
|
internal protein amino acid acetylation
|
|
autophagosome organization
|
|
mitotic DNA integrity checkpoint signaling
|
|
G1/S transition of mitotic cell cycle
|
|
nucleic acid phosphodiester bond hydrolysis
|
|
centrosome cycle
|
|
positive regulation of DNA-templated transcription, elongation
|
|
autophagosome assembly
|
|
RNA phosphodiester bond hydrolysis
|
|
tRNA methylation
|
|
protein deacetylation
|
|
protein deacylation
|
|
macromolecule deacylation
|
|
mitotic DNA damage checkpoint signaling
|
|
DNA-templated DNA replication maintenance of fidelity
|
|
histone deacetylation
|
|
RNA methylation
|
|
histone H3 acetylation
|
|
regulation of DNA repair
|
|
double-strand break repair via homologous recombination
|
|
post-Golgi vesicle-mediated transport
|
|
recombinational repair
|
|
vacuole organization
|
|
positive regulation of transcription initiation by RNA polymerase II
|
For Upregulation
After subsetting I do have 1128 genes that are down regulated. Up
regualted genes are mostly invovled in cancer activity. Most of the
pathwyas are quite invovled in cancerous activty. There is a lot
apoptosis and programmed cell death activities.
Upregulated_genes_filtered <- data.frame(
term_name = Upregulated_Gprofiler_validated$result$term_name[Upregulated_Gprofiler_validated$result$term_size < 200 & Upregulated_Gprofiler_validated$result$term_size > 1],
term_id = Upregulated_Gprofiler_validated$result$term_id[Upregulated_Gprofiler_validated$result$term_size < 200 &
Upregulated_Gprofiler_validated$result$term_size > 1],
source = Upregulated_Gprofiler_validated$result$source[Upregulated_Gprofiler_validated$result$term_size < 200 &
Upregulated_Gprofiler_validated$result$term_size > 1]
)
length(Upregulated_genes_filtered$term_name)
[1] 1128
knitr::kable(Upregulated_Gprofiler_validated$result$term_name[1:50], format = "html")
|
x
|
|
organonitrogen compound biosynthetic process
|
|
peptide metabolic process
|
|
translation
|
|
peptide biosynthetic process
|
|
organonitrogen compound metabolic process
|
|
amide metabolic process
|
|
amide biosynthetic process
|
|
cytoplasmic translation
|
|
cellular macromolecule metabolic process
|
|
cellular macromolecule biosynthetic process
|
|
protein metabolic process
|
|
metabolic process
|
|
cellular metabolic process
|
|
ATP synthesis coupled electron transport
|
|
mitochondrial ATP synthesis coupled electron transport
|
|
nitrogen compound metabolic process
|
|
respiratory electron transport chain
|
|
aerobic respiration
|
|
regulation of protein metabolic process
|
|
catabolic process
|
|
electron transport chain
|
|
aerobic electron transport chain
|
|
cellular respiration
|
|
oxidative phosphorylation
|
|
organic substance metabolic process
|
|
primary metabolic process
|
|
macromolecule catabolic process
|
|
protein localization
|
|
cellular macromolecule localization
|
|
macromolecule localization
|
|
organic substance catabolic process
|
|
protein catabolic process
|
|
establishment of protein localization
|
|
cellular catabolic process
|
|
programmed cell death
|
|
cell death
|
|
ribonucleoprotein complex biogenesis
|
|
cellular localization
|
|
organonitrogen compound catabolic process
|
|
apoptotic process
|
|
protein-containing complex organization
|
|
protein-containing complex assembly
|
|
intracellular transport
|
|
regulation of programmed cell death
|
|
generation of precursor metabolites and energy
|
|
energy derivation by oxidation of organic compounds
|
|
protein transport
|
|
cellular component biogenesis
|
|
ribose phosphate biosynthetic process
|
|
regulation of cell death
|
NA
NA
Part 18: Visualizations of the upregualted and the downregulated
genes
gprofiler2::gostplot(Upregulated_Gprofiler_validated) %>% plotly::layout(title = "Upregulated genes ", font = list(size = 10))
NA
Continuing
gprofiler2::gostplot(Downregulated_Gprofiler_validated) %>% plotly::layout(title = "Downregulated genes ", font = list(size = 10))
Part 19: GProfiler Analyses for the merged dataset
Complete_Gprofiler_Analyses <- gprofiler2::gost(query = merged_hits$Gene_symbol,
organism = "hsapiens",
exclude_iea = TRUE,
correction_method = "fdr",
sources = c("GO:BP", "REAC", "WP"))
Complete_Gprofiler_Analyses_filtered <- data.frame(term_name = Complete_Gprofiler_Analyses$result$term_name[Complete_Gprofiler_Analyses$result$term_size < 200 &
Complete_Gprofiler_Analyses$result$term_size > 1],
term_id = Complete_Gprofiler_Analyses$result$term_id[Complete_Gprofiler_Analyses$result$term_size < 200 &
Complete_Gprofiler_Analyses$result$term_size > 1],
source = Complete_Gprofiler_Analyses$result$source[Complete_Gprofiler_Analyses$result$term_size < 200 &
Complete_Gprofiler_Analyses$result$term_size > 1])
length(Complete_Gprofiler_Analyses_filtered$term_name)
[1] 1927
knitr::kable(Complete_Gprofiler_Analyses$result$term_name[1:100], format = "html")
|
x
|
|
cellular metabolic process
|
|
primary metabolic process
|
|
metabolic process
|
|
cellular macromolecule metabolic process
|
|
nitrogen compound metabolic process
|
|
organic substance metabolic process
|
|
macromolecule metabolic process
|
|
cellular nitrogen compound metabolic process
|
|
organonitrogen compound metabolic process
|
|
protein metabolic process
|
|
heterocycle metabolic process
|
|
nucleobase-containing compound metabolic process
|
|
cellular biosynthetic process
|
|
cellular response to stress
|
|
organic substance biosynthetic process
|
|
cellular aromatic compound metabolic process
|
|
biosynthetic process
|
|
organic cyclic compound metabolic process
|
|
intracellular transport
|
|
nucleic acid metabolic process
|
|
macromolecule modification
|
|
cellular catabolic process
|
|
catabolic process
|
|
establishment of localization in cell
|
|
macromolecule catabolic process
|
|
macromolecule biosynthetic process
|
|
protein modification process
|
|
cellular macromolecule catabolic process
|
|
cellular nitrogen compound biosynthetic process
|
|
RNA processing
|
|
cellular localization
|
|
gene expression
|
|
organonitrogen compound biosynthetic process
|
|
cellular macromolecule biosynthetic process
|
|
organelle organization
|
|
organic substance catabolic process
|
|
RNA metabolic process
|
|
cellular process
|
|
cellular response to DNA damage stimulus
|
|
protein localization to organelle
|
|
regulation of cellular metabolic process
|
|
translation
|
|
cellular macromolecule localization
|
|
regulation of nitrogen compound metabolic process
|
|
protein localization
|
|
mitotic cell cycle
|
|
peptide biosynthetic process
|
|
amide biosynthetic process
|
|
regulation of primary metabolic process
|
|
macromolecule localization
|
|
protein catabolic process
|
|
ribonucleoprotein complex biogenesis
|
|
mitotic cell cycle process
|
|
proteolysis involved in protein catabolic process
|
|
peptide metabolic process
|
|
modification-dependent macromolecule catabolic process
|
|
cellular component organization or biogenesis
|
|
amide metabolic process
|
|
modification-dependent protein catabolic process
|
|
intracellular protein transport
|
|
organonitrogen compound catabolic process
|
|
cell cycle
|
|
ubiquitin-dependent protein catabolic process
|
|
DNA metabolic process
|
|
regulation of metabolic process
|
|
regulation of cell cycle
|
|
mRNA metabolic process
|
|
positive regulation of nitrogen compound metabolic process
|
|
regulation of protein metabolic process
|
|
establishment of protein localization
|
|
regulation of macromolecule metabolic process
|
|
cellular component biogenesis
|
|
positive regulation of cellular metabolic process
|
|
positive regulation of nucleobase-containing compound metabolic process
|
|
ribosome biogenesis
|
|
protein transport
|
|
DNA repair
|
|
cell cycle process
|
|
cellular component organization
|
|
regulation of catabolic process
|
|
positive regulation of metabolic process
|
|
proteasomal protein catabolic process
|
|
ncRNA metabolic process
|
|
proteasome-mediated ubiquitin-dependent protein catabolic process
|
|
positive regulation of macromolecule biosynthetic process
|
|
positive regulation of cellular biosynthetic process
|
|
positive regulation of macromolecule metabolic process
|
|
protein modification by small protein conjugation or removal
|
|
regulation of cellular catabolic process
|
|
positive regulation of biosynthetic process
|
|
heterocycle biosynthetic process
|
|
regulation of macromolecule biosynthetic process
|
|
RNA splicing
|
|
process utilizing autophagic mechanism
|
|
autophagy
|
|
protein modification by small protein conjugation
|
|
regulation of cellular biosynthetic process
|
|
regulation of organelle organization
|
|
organic cyclic compound biosynthetic process
|
|
establishment of protein localization to organelle
|
Continuing
gprofiler2::gostplot(Complete_Gprofiler_Analyses) %>% plotly::layout(title = "Complete plot plot", font = list(size = 10))
Part 20:Interpretation
Do the over-representation results support conclusions or mechanism
discussed in the original paper ?
Yes the over-representation results we find is correlated to the
conclusion the authors make. They conclude that genes having higher GLI2
expression, more differentially expressed, are more possible to be EMT
genes. Additionally, we found there is always higher expression on GLI2
treatments given this is a strong oncogene acting in basal-sub-type
switching triggering EMT switching. As it is obvious from the
visualization the upregualted genes are more clustered and are much more
in the downregualted genes This supports the hypothesis of authors,
concluding the EMT genes to be higher expression than that of the
downregualted genes.
Can you find evidence, i.e. publications, to support some of the
results that you see. How does this evidence support your results ?
The paper (Pasca di Magliano et al.,2006) has already indicated
increase expression of GLI2 can lead to SHH gene reduction. This gene
has been known to be an oncogene associated with basal-sub-type
switching in PDAC. They activate GLI2 constantly which has the same
expected outcome in our data set having GLI2 expressing vectors with
constant Dox treatment. In conclusion these two paper findings correlate
each other. They show that the EMT genes to be abundant in their
biological functions and their pathway invovlement.
References
Adams, Christina R, Htet Htwe Htwe, Timothy Marsh, Aprilgate L Wang,
Megan L Montoya, Lakshmipriya Subbaraj, Aaron D Tward, Nabeel Bardeesy,
and Rushika M Perera. 2019. “Transcriptional Control of Subtype
Switching Ensures Adaptation and Growth of Pancreatic Cancer.”
Elife 8: e45313.
Allaire, JJ, Yihui Xie, Jonathan McPherson, Javier Luraschi, Kevin
Ushey, Aron Atkins, Hadley Wickham, Joe Cheng, Winston Chang, and
Richard Iannone. 2021.
rmarkdown: Dynamic
Documents for R.
https://github.com/rstudio/rmarkdown.
Davis, S., and P. Meltzer. 2007. “GEOquery: A Bridge Between the
Gene Expression Omnibus (GEO) and BioConductor.”
Bioinformatics 14: 1846–47.
Durinck, S., P. Spellman, E. Birney, and W. Huber. 2009. “Mapping
Identifiers for the Integration of Genomic Datasets with the
r/Bioconductor Package biomaRt.” Nature Protocols 4:
1184–91.
Gu, Zuguang. 2022. “Complex Heatmap Visualization.”
iMeta 1 (3): e43.
Gu, Zuguang, Lei Gu, Roland Eils, Matthias Schlesner, and Benedikt
Brors. 2014. “Circlize Implements and Enhances Circular
Visualization in r.” Bioinformatics 30 (19): 2811–12.
Magliano, Marina Pasca di, Shigeki Sekine, Alexandre Ermilov, Jenny
Ferris, Andrzej A Dlugosz, and Matthias Hebrok. 2006.
“Hedgehog/Ras Interactions Regulate Early Stages of Pancreatic
Cancer.” Genes & Development 20 (22): 3161–73.
R Core Team. 2022.
R: A Language and Environment for Statistical
Computing. Vienna, Austria: R Foundation for Statistical Computing.
https://www.R-project.org/.
Ritchie, Matthew E, Belinda Phipson, DI Wu, Yifang Hu, Charity W Law,
Wei Shi, and Gordon K Smyth. 2015. “Limma Powers Differential
Expression Analyses for RNA-Sequencing and Microarray Studies.”
Nucleic Acids Research 43 (7): e47–47.
Robinson, M. D., McCarthy DJ, and G. K. Smyth. 2010. “edgeR: A
Bioconductor Package for Differential Expression Analysis of Digital
Gene Expression Data.” Bioinformatics 26: 139–40.
LS0tDQp0aXRsZTogIkFzc2lnbm1lbnQgMiINCmRhdGU6ICIyMDIzLTAzLTA4Ig0KYXV0aG9yOiAiTWV0eXUgTWVsa29ueWFuIg0KYmlibGlvZ3JhcGh5OiBBMi5iaWINCm91dHB1dDogDQogIGh0bWxfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KLS0tDQoNCiogQmlvY29uZHVjdG9yIChAZHVyaW5jazIwMDlhKQ0KKiBSIGxhbmd1YWdlIChAcikNCiogQXJ0aWNsZSAoQGFkYW1zMjAxOXRyYW5zY3JpcHRpb25hbCkNCiogUm1hcmtkb3duIChAQWxsYWlyZV9ybWFya2Rvd25fRHluYW1pY19Eb2N1bWVudHNfMjAyMSkNCiogZWRnZVIgKEByb2JpbnNvbjIwMTBhKQ0KKiBHRU9xdWVyeSAoQGRhdmlzMjAwN2EpDQoqIFNISCAoQGRpMjAwNmhlZGdlaG9nKQ0KKiBMaW1tYSAoQHJpdGNoaWUyMDE1bGltbWEpDQoqIENvbXBsZXhIZWF0TWFwIChAZ3UyMDIyY29tcGxleCkNCiogQ2lyY2xpemUgKEBndTIwMTRjaXJjbGl6ZSkNCg0KIyMjIEluc3RhbGxpbmcgRGVwZW5kZW5jaWVzDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJCaW9jTWFuYWdlciIsIHF1aWV0bHkgPSBUUlVFKSl7DQogIGluc3RhbGwucGFja2FnZXMoIkJpb2NNYW5hZ2VyIil9DQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImVkZ2VSIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgQmlvY01hbmFnZXI6Omluc3RhbGwoImVkZ2VSIil9DQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkdFT3F1ZXJ5IiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgQmlvY01hbmFnZXI6Omluc3RhbGwoIkdFT3F1ZXJ5Iil9DQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkNvbXBsZXhIZWF0bWFwIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgQmlvY01hbmFnZXI6Omluc3RhbGwoIkNvbXBsZXhIZWF0bWFwIil9DQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImxpbW1hIiwgcXVpZXRseSA9IFRSVUUpKXsNCiAgQmlvY01hbmFnZXI6Omluc3RhbGwoImxpbW1hIil9DQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoIkV4cHJlc3Npb25TZXQiLCBxdWlldGx5ID0gVFJVRSkpew0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiRXhwcmVzc2lvblNldCIpfQ0KaWYgICghcmVxdWlyZU5hbWVzcGFjZSgiY2lyY2xpemUiLCBxdWlldGx5ID0gVFJVRSkpew0KICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiY2lyY2xpemUiKX0NCmlmICghcmVxdWlyZU5hbWVzcGFjZSgiZ3Byb2ZpbGVyMiIsIHF1aWV0bHkgPSBUUlVFKSkNCiAgICBCaW9jTWFuYWdlcjo6aW5zdGFsbCgiZ3Byb2ZpbGVyMiIpDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImthYmxlRXh0cmEiLCBxdWlldGx5ID0gVFJVRSkpDQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoImthYmxlRXh0cmEiKQ0KaWYgKCFyZXF1aXJlTmFtZXNwYWNlKCJwbG90bHkiLCBxdWlldGx5ID0gVFJVRSkpDQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoInBsb3RseSIpDQppZiAoIXJlcXVpcmVOYW1lc3BhY2UoImRwbHlyIiwgcXVpZXRseSA9IFRSVUUpKQ0KICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJkcGx5ciIpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShwbG90bHkpDQoNCmBgYA0KIyMjIFBhcnQgMTogTG9hZGluZyB0aGUgbm9ybWFsaXplZCBnZW5lIGRhdGENClRoZSBub3JtYWxpemVkIGRhdGEgaGFzIGFscmVhZHkgYmVlbiB3cml0dGVuIGludG8gYSB0ZXh0IGZpbGUgYnkgdGhlIHByZXZpb3VzDQpBc3NpZ25tZW50IDEuIEZvciBiZXR0ZXIgYXNzZXNzbWVudCwgSSBoYXZlIGluZGljYXRlZCBpdCBvbiB0aGUgZmlsZSB1cGxvYWRlZC4NCmBgYHtyIGV2YWw9VFJVRSwgbWVzc2FnZT1GQUxTRX0NCm5vcm1hbGl6ZWRfY291bnRfZGF0YSA8LSByZWFkLnRhYmxlKGZpbGU9ZmlsZS5wYXRoKGdldHdkKCksICJub3JtYWxpemVkX2NvdW50c19hbm5vdGF0ZWQiKQ0KLCBoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGNoZWNrLm5hbWVzID0gRkFMU0UgKQ0KDQprbml0cjo6a2FibGUobm9ybWFsaXplZF9jb3VudF9kYXRhWzE6MTAsMTo3XSwgdHlwZT0icGlwZSIpDQpgYGANCiMjIyBQYXJ0IDI6IERlZmluaW5nIFBvcnRpb25zIG9mIHRoZSBIZWF0bWFwIE1hdHJpeCA8YnI+DQpJIGFtIGRlZmluaW5nIHRoZSBlbGVtZW50cyBvZiB0aGUgbm9ybWFsaXplZCBkYXRhIG1hdHJpeCB3aGljaCBJIHdpbGwgDQpiZSB1c2luZyBmb3IgdGhlIGhlYXRtYXAgbGF0ZXIuDQpgYGB7ciBldmFsPVRSVUUsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0V9DQpoZWF0bWFwX21hdHJpeCA8LSBub3JtYWxpemVkX2NvdW50X2RhdGFbLDI6N10NCmNvbG5hbWVzKG5vcm1hbGl6ZWRfY291bnRfZGF0YSlbMV0gPC0gIkdlbmVfc3ltYm9sIg0Kcm93bmFtZXMoaGVhdG1hcF9tYXRyaXgpIDwtIG5vcm1hbGl6ZWRfY291bnRfZGF0YSRHZW5lX3N5bWJvbA0KY29sbmFtZXMoaGVhdG1hcF9tYXRyaXgpIDwtIGNvbG5hbWVzKG5vcm1hbGl6ZWRfY291bnRfZGF0YVssMjo3XSkNCmhlYXRtYXBfbWF0cml4IDwtIHQoc2NhbGUodChoZWF0bWFwX21hdHJpeCkpKQ0KYGBgDQojIyMgUGFydCAzOiBDcmVhdGluZyBIZWF0bWFwIDxicj4NClRoZSBoZWF0bWFwIHVzZXMgZGlmZmVyZW50IGNvbG9ycyBmb3IgdGhlIGV4cHJlc3Npb24gZGF0YS4gVGhlIGhlYXRtYXAgaGFzIG1hbnkgDQpnZW5lcyBjbHVzdGVyZWQgYmFzZWQgb24gdGhlaXIgZXhwcmVzc2lvbiBhdCBkaWZmZXJlbnQgbGV2ZWxzIHN1Y2ggYXMgY29udHJvbCANCihFQTEsRUEyLEVCMSkgb3IgdGhlIGNlbGxzIHRyZWF0ZWQgd2l0aCBHTEkyIChHMUEsRzJBLEcxQikuDQpgYGB7ciwgd2FybmluZz1GQUxTRSwgbWVzc2FnZT1GQUxTRX0NCmlmKG1pbihoZWF0bWFwX21hdHJpeCkgPT0gMCl7DQogICBoZWF0bWFwX2NvbCA9IGNpcmNsaXplOjpjb2xvclJhbXAyKGMoIDAsIG1heChoZWF0bWFwX21hdHJpeCkpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgYygid2hpdGUiLCAicHVycGxlIikpDQp9IGVsc2Ugew0KICBoZWF0bWFwX2NvbCA9IGNpcmNsaXplOjpjb2xvclJhbXAyKGMobWluKGhlYXRtYXBfbWF0cml4KSwgMCwNCiAgICAgICAgIG1heChoZWF0bWFwX21hdHJpeCkpLCBjKCJkYXJrZ3JlZW4iLCAid2hpdGUiLCAicHVycGxlIikpDQp9DQpmaXJzdF9oZWF0bWFwIDwtIENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwKGFzLm1hdHJpeChoZWF0bWFwX21hdHJpeCksDQogICAgIHNob3dfcm93X2RlbmQgPSBUUlVFLCBzaG93X2NvbHVtbl9kZW5kID0gVFJVRSwNCiAgICAgY29sPWhlYXRtYXBfY29sLCBzaG93X2NvbHVtbl9uYW1lcyA9IFRSVUUsDQogICAgIHNob3dfcm93X25hbWVzID0gRkFMU0UsIHNob3dfaGVhdG1hcF9sZWdlbmQgPSBUUlVFKQ0KZmlyc3RfaGVhdG1hcA0KYGBgDQojIyMgUGFydCA0OiBTUFAxIEVNVCBHZW5lcy1Db25jbHVzaW9uIGp1c3RpZmljYXRpb24gPGJyPg0KU1BQMSBpcyBhbiBFTVQgZ2VuZXMgSXQgc2hvd3MgaGlnaGVyIGV4cHJlc3Npb24gd2hlbiB0cmVhdGVkIHdpdGggR0xJMiBjb21wYXJlIA0KdG8gZW1wdHkgdmVjdG9yIGNvbnRyb2wgY2VsbHMgKEVWKS4gVGhpcyBoYXMgYmVlbiBhbHNvIHByb3ZlZCBieSB0aGUgYXV0aG9ycy4NCkhvd2V2ZXIsIGluZGljYXRpbmcgdGhpcyBhZ2FpbiB3b3VsZCBzdHJlbmd0aGVuIHRoZSBoeXBvdGhlc2lzIGNvcnJlc3BvbmRpbmcgdG8NCkRveCB0cmVhdGVkIGNlbGxzIGhhdmluZyBHTEkyIHZlY3RvciBzaG93IGhpZ2hlciBFTVQgZ2VuZSBleHByZXNzaW9uICBhcw0Kb3Bwb3NlZCB0byBjb250cm9scyBoYXZpbmcgZW1wdHkgdmVjdG9yIHNob3dpbmcgbGVzcyBleHByZXNzaW9uIG9mIHRoZSBnZW5lcy4NCmBgYHtyIG1lc3NhZ2U9RkFMU0V9DQpHTEkyX3RyZWF0bWVudF9zYW1wbGVzIDwtIGdyZXAoY29sbmFtZXMobm9ybWFsaXplZF9jb3VudF9kYXRhKSxwYXR0ZXJuID0gIlxcRyIpDQpFVl90cmF0bWVudF9zYW1wbGVzIDwtIGdyZXAoY29sbmFtZXMobm9ybWFsaXplZF9jb3VudF9kYXRhKSxwYXR0ZXJuID0gIlxcRSIpDQpnZW5lX29mX2ludGVyZXN0IDwtIHdoaWNoKG5vcm1hbGl6ZWRfY291bnRfZGF0YSRHZW5lX3N5bWJvbCA9PSAiU1BQMSIpDQoNCllBUENfR0xJMl9zYW1wbGVzIDwtIHQobm9ybWFsaXplZF9jb3VudF9kYXRhW2dlbmVfb2ZfaW50ZXJlc3QsNTo3XSkNCmNvbG5hbWVzKFlBUENfR0xJMl9zYW1wbGVzKSA8LSBjKCJHTEkyX3ZlY3Rvcl9jZWxscyIpDQoNCllBUENfRVZfc2FtcGxlcyA8LSB0KG5vcm1hbGl6ZWRfY291bnRfZGF0YVtnZW5lX29mX2ludGVyZXN0LDI6NF0pDQpjb2xuYW1lcyhZQVBDX0VWX3NhbXBsZXMpIDwtIGMoIkVtcHR5X1ZlY3Rvcl9jZWxscyIpDQoNCllBUENfR0xJMl9zYW1wbGVzDQpZQVBDX0VWX3NhbXBsZXMNCmBgYA0KIyMjIFBhcnQgNTogVC10ZXN0IGJldHdlZW4gRVYgYW5kIEdMSTINCkdMSTIgdHJlYXRlZCBjZWxscyBhcmUgZGlmZmVyZW50IGluIHRlcm1zIG9mIHRoZWlyIGV4cHJlc3Npb24gZnJvbSB0aGUgDQplbXB0eSB2ZWN0b3IgY2VsbHMuIFAgdmFsdWUgKDAuMDMxMzUpIDwgMC4wNS4gSW5kZWVkIHRoaXMgc2hvd3MgdGhlcmUgaXMgDQpzaWduaWZpY2FudCBkaWZmZXJlbmNlLiBIb3dldmVyLCB0aGlzIHJlcXVpcmVzIHRvIHNlZSBpZiBHTEkyIHRyZWF0bWVudHMgDQpzaG93IGRpZmZlcmVuY2UgYW1vbmcgb25lIGFub3RoZXIgc28gdGhlIGNvbnRyb2wgY2VsbHMuDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KdC50ZXN0KHg9dChZQVBDX0dMSTJfc2FtcGxlcyksIHk9dChZQVBDX0VWX3NhbXBsZXMpKQ0KYGBgDQojIyMgUEFSVCA2OiBNRFMgUGxvdCBmb3IgU2FtcGxlIENsdXN0ZXJpbmcNClRoZSBNRFMgcGxvdCBhbGxvd2VkIHRvIHZpc3VhbGl6ZSB0aGUgZGlmZmVyZW5jZSB3aXRoaW4gdGhlIGRpZmZlcmVudCBjZWxsIHR5cGVzDQpFYXJsaWVyIGV4YW1wbGVzIG9mIE1EUyBwbG90IHNob3dlZCBzaW1pbGFyIHJlc3VsdHMuIEkgaHlwb3RoZXNpemUgdGhhdCBHTEkyDQpleHByZXNzaW9uIGlzIGhpZ2hlciB0aGFuIGNvbnRyb2wgY2VsbCdzIGV4cHJlc3Npb24gbGV2ZWxzIGR1ZSB0byBET1ggaW5kdWN0aW9uDQpvZiBFTVQgZ2VuZXMuIEluIGdlbmVyYWwgSSBoYXZlIG9ic2VydmVkIEdsaTIgY2VsbHMgdG8gYmUgbGVzcyBjbHVzdGVyZWQsIA0KZHVlIHRvIGhpZ2hlciBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhbW9uZyBHTEkyIGNlbGxzLg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCmxpbW1hOjpwbG90TURTKGhlYXRtYXBfbWF0cml4LGNvbD1jKHJlcCgiZGFya2dyZWVuIiwzKSwgcmVwKCJibHVlIiwzKSkpDQpgYGANCiMjIyBQYXJ0IDc6IE1vZGVsIEJ1aWxkaW5nIG9mIEdMSTIgZXhwcmVzc2lvbiBzdGF0dXMNClRoZSBtb2RlbCBJIGFtIGJ1aWxkaW5nIGlzIGJhc2VkIHVwb24gR0xJMiBleHByZXNzaW9uIHN0YXR1cyBvZiBnZW5lcyB0aGF0DQphcmUgc2hvd2luZyBoaWdoZXIgZXhwcmVzc2lvbiB3aXRoIHNpZ25pZmljYW50IGluZGljYXRpb25zIG9mIHRoZSBkaWZmZXJlbnRpYWwgDQpleHByZXNzaW9uLg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCnNhbXBsZXMgPC0gZGF0YS5mcmFtZShsYXBwbHkoY29sbmFtZXMobm9ybWFsaXplZF9jb3VudF9kYXRhKVsyOjddLA0KICAgICAgICAgICBGVU49ZnVuY3Rpb24oeCl7dW5saXN0KHN0cnNwbGl0KHgsIHNwbGl0ID0gIlswLTldIikpW2MoMSldfSkpDQoNCmNvbG5hbWVzKHNhbXBsZXMpIDwtIGNvbG5hbWVzKGNvbG5hbWVzKG5vcm1hbGl6ZWRfY291bnRfZGF0YSlbMjo3XSkNCnJvd25hbWVzKHNhbXBsZXMpIDwtIGMoIlRyZWF0bWVudHMiKQ0Kc2FtcGxlcyA8LSBkYXRhLmZyYW1lKHQoc2FtcGxlcykpDQprbml0cjo6a2FibGUoc2FtcGxlcywgdHlwZSA9ICJwaXBlIikgDQoNCllSR19tb2RlbCA8LSBtb2RlbC5tYXRyaXgoIH4gc2FtcGxlcyRUcmVhdG1lbnRzKQ0Ka25pdHI6OmthYmxlKFlSR19tb2RlbFsxOjYsXSwgdHlwZSA9ICJwaXBlIikNCmBgYA0KIyMjIFBhcnQgODogTW9kZWwgRml0dGluZyBhbmQgRGlmZmVyZW50aWFsIEV4cHJlc3Npb24gQ2FsY3VsYXRpb24NClRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBkYXRhIG1hdHJpeCBjb3JyZXNwb25kaW5nIHRvIGdlbmUgc3ltYm9scyB3ZXJlIG1lcmdlZA0Kd2l0aCB0aGUgbWF0cml4IHRoYXQgaGFzIHRoZSBmaXR0ZWQgbW9kZWwuIFRoZSBCZW5qYW1pbi1ob2NoYmVyZyBjb3JyZWN0aW9uIA0KbWV0aG9kIHdhcyBhcHBsaWVkIHRvIGFkanVzdCB0aGUgZXhwcmVzc2lvbiBkYXRhLg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCmV4cHJlc3Npb25NYXRyaXggPC0gYXMubWF0cml4KG5vcm1hbGl6ZWRfY291bnRfZGF0YVssMjo3XSkNCnJvd25hbWVzKGV4cHJlc3Npb25NYXRyaXgpIDwtIG5vcm1hbGl6ZWRfY291bnRfZGF0YSRHZW5lX3N5bWJvbA0KY29sbmFtZXMoZXhwcmVzc2lvbk1hdHJpeCkgPC0gY29sbmFtZXMobm9ybWFsaXplZF9jb3VudF9kYXRhKVsyOjddDQpzZXRfZXhwcmVzc2lvbl9tYXRyaXggPC0gQmlvYmFzZTo6RXhwcmVzc2lvblNldChhc3NheURhdGEgPSBleHByZXNzaW9uTWF0cml4KQ0KDQpmaXQgPC0gbGltbWE6OmxtRml0KHNldF9leHByZXNzaW9uX21hdHJpeCwgWVJHX21vZGVsKQ0KDQpmaXRfQmF5ZXMgPC0gbGltbWE6OmVCYXllcyhmaXQsIHRyZW5kID0gVFJVRSkNCg0KQkhfbWV0aG9kX2ZpdCA8LSBsaW1tYTo6dG9wVGFibGUoZml0X0JheWVzLA0KICAgICAgICAgICAgICAgICAgIGNvZWYgPSBuY29sKFlSR19tb2RlbCksDQogICAgICAgICAgICAgICAgICAgYWRqdXN0Lm1ldGhvZCA9ICJCSCIsDQogICAgICAgICAgICAgICAgICAgbnVtYmVyID0gbnJvdyhleHByZXNzaW9uTWF0cml4KSkNCg0KbWVyZ2VkX2hpdHMgPC0gbWVyZ2Uobm9ybWFsaXplZF9jb3VudF9kYXRhJEdlbmVfc3ltYm9sLA0KICAgICAgICAgICAgICAgICAgICAgQkhfbWV0aG9kX2ZpdCwNCiAgICAgICAgICAgICAgICAgICAgIGJ5Lnk9MCxieS54PTEsDQogICAgICAgICAgICAgICAgICAgICBhbGwueT1UUlVFKQ0KDQptZXJnZWRfaGl0cyA8LSBtZXJnZWRfaGl0c1tvcmRlcihtZXJnZWRfaGl0cyRQLlZhbHVlKSxdDQpjb2xuYW1lcyhtZXJnZWRfaGl0cykgPC0gYygiR2VuZV9zeW1ib2wiLCJsb2dGQyIsICJBdmVFeHByIiwgInQiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIlAuVmFsdWUiLCJhZGouUC5WYWwiLCAiQiIpDQpyb3duYW1lcyhtZXJnZWRfaGl0cykgPC0gMTpucm93KG1lcmdlZF9oaXRzKQ0KDQprbml0cjo6a2FibGUobWVyZ2VkX2hpdHNbMToxMCwxOjddLCB0eXBlID0gInBpcGUiLCByb3cubmFtZXMgPSBGQUxTRSwpDQpgYGANCiMjIyBQYXJ0IDk6IFAtdmFsdWUgQXNzZXNzbWVudA0KVGhlIHAtdmFsdWUgd2FzIGFkanVzdGVkIHRvIGhhdmUgbW9yZSBzdHJpbmdlbnQgcmVzdWx0cy4gTm9ybWFsbHkgc2lnbmlmaWNhbnQgDQpwLXZhbHVlIGlzIHNldCB0byAwLjA1LiBIb3dldmVyLCBJIHdhbnRlZCB0byBiZSBtb3JlIHN0cmluZ2VudCBvbiBteSByZXN1bHRzDQphbmQgaW5kaWNhdGUgdGhlIHNwZWNpZmljIEVNVCBnZW5lcy4gUHJvYmFibGUgZ2VuZXMgYXJlIDc0MS4gSG93ZXZlciwNCnRoZXJlIGFyZSAyNyBnZW5lcyB0aGF0IGhhdmUgc2lnbmlmaWNhbnQgcG90ZW50aWFsIHRvIGJlIGFuIEVNVCBnZW5lLg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCmxlbmd0aCh3aGljaChtZXJnZWRfaGl0cyRQLlZhbHVlIDwgMC4wMDA1KSkNCg0KbGVuZ3RoKHdoaWNoKG1lcmdlZF9oaXRzJGFkai5QLlZhbCA8IDAuMDAwNSkpDQpgYGANCiMjIyBQYXJ0IDEwOiBNb2RlbCBWaXN1YWxpemF0aW9uIA0KVGhpcyBwYXJ0IG9mIHRoaXMgYXNzaWdubWVudCBhaW1zIHRvIGRldGVjdCBTUFAxJ3Mgcm9sZSBvbiBob3cgR0xJMiBjZWxscyBhcmUNCm1vcmUgZGlmZmVyZW50bHkgZXhwcmVzc2VkIGFuZCBkbyBoYXZlIGhpZ2hlciBkaWZmZXJlbmNlIHRoYW4gdGhlIGNvbnRyb2wgY2VsbHMuDQpJdCBpcyBldmlkZW50IHRoYXQsIHdpdGggbW9yZSBzdHJpbmdlbnQgcC12YWx1ZSwgdGhlIHNpZ25pZmljYW50IHBvcnRpb24gKDc0MSkNCm9mIGFib3V0IDExNTAwIGdlbmVzIGFyZSBzaG93aW5nIGZlYXR1cmVzIG9mIEVNVCBnZW5lcw0KYGBge3IgIG1lc3NhZ2U9RkFMU0V9DQptb2RlbF9wdmFsdWVzIDwtIGRhdGEuZnJhbWUoR2VuZV9zeW1ib2wgPSBtZXJnZWRfaGl0cyRHZW5lX3N5bWJvbCwgDQpwdmFsdWUgPSBtZXJnZWRfaGl0cyRQLlZhbHVlKQ0KDQptb2RlbF9wdmFsdWVzJGNvbG9yIDwtICJibGFjayINCm1vZGVsX3B2YWx1ZXMkY29sb3JbbW9kZWxfcHZhbHVlcyRwdmFsdWUgPCAwLjAwMDVdIDwtICJvcmFuZ2UiDQogICAgDQpTUFAxIDwtIG5vcm1hbGl6ZWRfY291bnRfZGF0YSRHZW5lX3N5bWJvbFt3aGljaChub3JtYWxpemVkX2NvdW50X2RhdGEkR2VuZV9zeW1ib2wgPT0gIlNQUDEiKV0NCm1vZGVsX3B2YWx1ZXMkY29sb3JbbW9kZWxfcHZhbHVlcyRHZW5lX3N5bWJvbD09IFNQUDFdIDwtICJyZWQiDQoNCnBsb3QobW9kZWxfcHZhbHVlcyRwdmFsdWUsDQogICAgIGNvbCA9IG1vZGVsX3B2YWx1ZXMkY29sb3IsDQogICAgIHhsYWIgPSAiTnVtYmVyIG9mIEdlbmVzIHdpdGhpbiB0aGUgRGF0YXNldCIsDQogICAgIHlsYWIgPSJQLXZhbHVlIiwNCiAgICAgbWFpbj0iUCB2YWx1ZSBkaXN0cmlidXRpb24gb2YgRU1UIEdlbmVzIikNCg0KcG9pbnRzKG1vZGVsX3B2YWx1ZXNbd2hpY2gobW9kZWxfcHZhbHVlcyRHZW5lX3N5bWJvbCA9PSAiU1BQMSIpLCAxOjJdLA0KICAgICAgIHBjaCA9IDIwLCBjb2w9InJlZCIsIGNleD0xLjUpDQpsZWdlbmQoMCwgMSwgbGVnZW5kPWMoIlNQUDEiKSwgZmlsbD1jKCJyZWQiKSkNCmBgYA0KIyMjIFBhcnQgMTE6IENsdXN0ZXJlZCBIZWF0bWFwIHdpdGggTW9yZSBTdHJpbmdlbnQgVmFsdWVzDQpXaXRoIG1vcmUgc3RyaW5nZW50IGdlbmUgc2l6ZSBJIHdhcyBhYmxlIHRvIHNlZSBjbGVhbmVyIGRpZmZlcmVuY2UgYmV0d2VlbiBHTEkyDQphbmQgdGhlIGNvbnRyb2wgY2VsbHMuIFRoZSBjbHVzdGVyZWQgZ2VuZXMgYXJlIHRoZSBzeW1tZXRyaWMgZWFjaCBvdGhlciBhY3Jvc3MNCnRoZSBkaWFnb25hbHMuIFRoZSBoaWdoIGV4cHJlc3Npb24gc2hvd2luZyBnZW5lcyBvbiB0aGUgR0xJMidzIHNpZGUgaXMgbG93ZXIgb24gDQp0aGUgRVYnIHNpZGUuIFRvcCBoaXRzIGFyZSBhc3Nlc3NlZCBvbiB0aGUgc3RyaW5nZW50IHAtdmFsdWUgb2YgMC4wMDA1Lg0KVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiB0aGUgZmlyc3QgYW5kIHRoZSBsYXRlc3QgaGVhdG1hcCBzaG93cyB0aGVyZSBpcyBzaWduaWZpY2FudCBkaWZmZXJlbmNlIA0KaW4gdGVybXMgb2YgZ2VuZSBleHByZXNzaW9uIHdob3NlIGV4cHJlc3Npb24gaXMgcmVwcmVzZW50ZWQgZm9yIGVhY2ggcmVzcGVjdGl2ZSBUcmVhdG1lbnRzDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KdG9wX2hpdHMgPC0gbWVyZ2VkX2hpdHMkR2VuZV9zeW1ib2xbbWVyZ2VkX2hpdHMkUC5WYWx1ZSA8IDAuMDAwNV0NCmhlYXRtYXBfbWF0cml4X3RvcGhpdHMgPC0gdChzY2FsZSh0KGhlYXRtYXBfbWF0cml4W3doaWNoKHJvd25hbWVzKGhlYXRtYXBfbWF0cml4KSANCiAgICAgICAgICAgICAgICAgICAgICAgJWluJSB0b3BfaGl0cyksXSkpKQ0KDQppZihtaW4oaGVhdG1hcF9tYXRyaXhfdG9waGl0cykgPT0gMCl7DQpoZWF0bWFwX2NvbCA9IGNpcmNsaXplOjpjb2xvclJhbXAyKGMoIDAsIG1heChoZWF0bWFwX21hdHJpeF90b3BoaXRzKSksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjKCAid2hpdGUiLCAicHVycGxlIikpDQp9IGVsc2V7DQpoZWF0bWFwX2NvbCA9IGNpcmNsaXplOjpjb2xvclJhbXAyKGMobWluKGhlYXRtYXBfbWF0cml4X3RvcGhpdHMpLCAwLA0KICAgICBtYXgoaGVhdG1hcF9tYXRyaXhfdG9waGl0cykpLCBjKCJkYXJrZ3JlZW4iLCAid2hpdGUiLCAicHVycGxlIikpDQp9DQpsYXRlc3RfaGVhdG1hcCA8LSBDb21wbGV4SGVhdG1hcDo6SGVhdG1hcChhcy5tYXRyaXgoaGVhdG1hcF9tYXRyaXhfdG9waGl0cyksDQpzaG93X3Jvd19kZW5kID0gVFJVRSwgc2hvd19jb2x1bW5fZGVuZCA9IFRSVUUsIGNvbD1oZWF0bWFwX2NvbCwNCnNob3dfY29sdW1uX25hbWVzID0gVFJVRSwgc2hvd19yb3dfbmFtZXMgPSBGQUxTRSwgc2hvd19oZWF0bWFwX2xlZ2VuZCA9IFRSVUUpDQpsYXRlc3RfaGVhdG1hcA0KZmlyc3RfaGVhdG1hcA0KYGBgDQojIyMgUGFydCAxMjogRGF0YXNldCBGaWx0ZXJpbmcgYW5kIERhdGEgRXh0cmFjdGluZw0KVGhlIHByZXZpb3VzbHkgZXh0cmFjdGVkIEdTRTEzMTIyMiBkYXRhIGZyb20gZ2VuZSBvbW5pYnVzIGV4cHJlc3Npb24gKEdFTykgaXMgDQpleHRyYWN0ZWQgc2VwYXJhdGVseS4gVGhlIGxvdyBjb3VudCBwb3J0aW9ucyBvZiB0aGUgZGF0YSBmaWx0ZXJlZCBhbmQgYSBuZXcNCm1hdHJpeCB3YXMgY3JlYXRlZC4NCmBgYHtyIG1lc3NhZ2U9RkFMU0Usd2FybmluZz1GQUxTRSx3YXJuaW5nPUZBTFNFfQ0KZGF0YSA9IEdFT3F1ZXJ5OjpnZXRHRU9TdXBwRmlsZXMoIkdTRTEzMTIyMiIpDQpkYXRhbmFtZXMgPSByb3duYW1lcyhkYXRhKQ0KDQpHTEkyX2V4cCA9cmVhZC5kZWxpbShkYXRhbmFtZXNbMV0saGVhZGVyPVRSVUUsY2hlY2submFtZXMgPSBGQUxTRSkNCg0KY291bnRfcGVyX21zID0gZWRnZVI6OmNwbShHTEkyX2V4cFssMzo4XSkNCnJvd25hbWVzKGNvdW50X3Blcl9tcykgPC0gR0xJMl9leHBbLDJdDQoNCnJvd3NfZmlsdGVyZWQgPSByb3dTdW1zKGNvdW50X3Blcl9tcyA+MSkgPj0gNg0KR0xJMl9leHBfZmlsdGVyZWQgPSBHTEkyX2V4cFtyb3dzX2ZpbHRlcmVkLF0NCg0KZmlsdGVyZWRfR0xJMl9tYXRyaXggPC0gYXMubWF0cml4KEdMSTJfZXhwX2ZpbHRlcmVkWywzOjhdKQ0Kcm93bmFtZXMoZmlsdGVyZWRfR0xJMl9tYXRyaXgpIDwtIEdMSTJfZXhwX2ZpbHRlcmVkJGdlbmUNCmhlYWQoR0xJMl9leHBfZmlsdGVyZWQpWzE6OF0NCmBgYA0KIyMjIFBhcnQgMTM6IEdyb3VwaW5nIEJhc2VkIG9uIHRoZSBDZWxsIFR5cGVzDQpUaGUgc2ltaWxhciBncm91cGluZyB3YXMgZG9uZSBwcmV2aW91c2x5LiBIb3dldmVyIHRoaXMgdGltZSBkaXNwZXJzaW9uIHZhbHVlcywNCm5vcm1hbGl6YXRpb24gZmFjdG9ycyBhbmQgZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gbW9kZWwgZml0dGluZyBpcyBhcHBsaWVkDQp0byB0aGUgc2FtcGxlcyBvZiBHTEkyIHRyZWF0bWVudHMuDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KZ3JvdXBlZF90cmVhdG1lbnRzIDwtIGRhdGEuZnJhbWUobGFwcGx5KGNvbG5hbWVzKEdMSTJfZXhwX2ZpbHRlcmVkKVszOjhdLA0KICAgICAgICAgICAgICAgIEZVTj1mdW5jdGlvbih4KXt1bmxpc3Qoc3Ryc3BsaXQoeCwgc3BsaXQgPSAiWzAtOV0iKSlbYygxKV19KSkNCmNvbG5hbWVzKGdyb3VwZWRfdHJlYXRtZW50cykgPC0gY29sbmFtZXMoR0xJMl9leHApWzM6OF0NCnJvd25hbWVzKGdyb3VwZWRfdHJlYXRtZW50cykgPC0gYygiY2VsbF90eXBlIikNCmdyb3VwZWRfdHJlYXRtZW50c19ub3JtYWxpemVkIDwtIGRhdGEuZnJhbWUodChncm91cGVkX3RyZWF0bWVudHMpKQ0KZCA9IGVkZ2VSOjpER0VMaXN0KGNvdW50cz1maWx0ZXJlZF9HTEkyX21hdHJpeCwgZ3JvdXAgPSBncm91cGVkX3RyZWF0bWVudHNfbm9ybWFsaXplZCRjZWxsX3R5cGUpDQoNCm1vZGVsX2Rlc2lnbl9jZWxsdHlwZXMgPC0gbW9kZWwubWF0cml4KH5ncm91cGVkX3RyZWF0bWVudHNfbm9ybWFsaXplZCRjZWxsX3R5cGUrMCkNCmQgPC0gZWRnZVI6OmVzdGltYXRlRGlzcChkLCBtb2RlbF9kZXNpZ25fY2VsbHR5cGVzKQ0KZCA8LSBlZGdlUjo6Y2FsY05vcm1GYWN0b3JzKGQpDQpmaXQgPC0gZWRnZVI6OmdsbVFMRml0KGQsIG1vZGVsX2Rlc2lnbl9jZWxsdHlwZXMpDQpxbGZfdGVzdC5HTEkydnNFViA8LSBlZGdlUjo6Z2xtUUxGVGVzdChmaXQsIGNvZWYgPSAiZ3JvdXBlZF90cmVhdG1lbnRzX25vcm1hbGl6ZWQkY2VsbF90eXBlWVJHIikNCmBgYA0KIyMjIFBhcnQgMTQ6IFNpZ25pZmljYW50IFJlc3VsdHMgd2l0aGluIHRoZSBGaXR0ZWQgTW9kZWwNCldpdGggbW9yZSBzdHJpbmdlbnQgcC12YWx1ZSBJIHdhcyBhYmxlIHRvIGFzc2VzcyB0aGUgY3JpdGljYWwgdGhyZXNob2xkIGZvciANCnRoZSBleHByZXNzaW9uIHRocmVzaG9sZC4gSSBzZXQgdGhlIHAtdmFsdWUgYXMgMC4wMDA1LiBJIGRlY2lkZWQgdG8gcHV0IGl0IGJ5DQphZGp1c3RpbmcgYW5kIG9ic2VydmluZyBhbnkgZGlmZmVyZW5jZS4gVGhlIGRpZmZlcmVuY2UgYmV0d2VlbiBwLXZhbHVlIDAuMDA1IGFuZCANCnAtdmFsdWUgMC4wMDA1IGlzIG9uZS4gVGhpcyBtZWFucyB0aGlzIHAtdmFsdWUgaXMgc2FmZSB0byBhc3N1bWUgYXMgYSB0aHJlc2hvbGQNCmZvciBzaWduaWZpY2FuY2UgYW1vbmcgdGhlc2UgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2luZyBnZW5lcy4NCmBgYHtyIG1lc3NhZ2U9RkFMU0V9DQpxbGZfdG9wX2hpdHMgPC0gZWRnZVI6OnRvcFRhZ3MocWxmX3Rlc3QuR0xJMnZzRVYsc29ydC5ieSA9ICJQVmFsdWUiLCBuID0gbnJvdyhmaWx0ZXJlZF9HTEkyX21hdHJpeCkpDQoNCmhlYWQocWxmX3RvcF9oaXRzKQ0KDQpsZW5ndGgod2hpY2gocWxmX3RvcF9oaXRzJHRhYmxlJFBWYWx1ZSA8IDAuMDAwNSkpDQogICAgICAgICAgIA0KbGVuZ3RoKHdoaWNoKHFsZl90b3BfaGl0cyR0YWJsZSRGRFIgPCAwLjAwMDUpKQ0KbGVuZ3RoKHdoaWNoKHFsZl90b3BfaGl0cyR0YWJsZSRsb2dGQyA8IDApKQ0KYGBgDQojIyMgUGFydCAxNTogVGhyZXNob2xkZWQgR2VuZSBMaXN0IGFuZCBGaW5hbCBFTVQgR2VuZSBEZXRlY3Rpb24NClRoZSB0aHJlc2hvbGQgd2FzIGNhbGN1bGF0ZWQgYW5kIGJhc2VkIGl0cyB2YWx1ZSBJIGFzc2Vzc2VkIHRoZSBob3cgbWFueSBnZW5lcyANCmFjdHVhbGx5IHNob3cgdHJhaXRzIHNpbWlsYXIgdG8gR0xJMi4gSSB1c2VkIFAgdmFsdWUgMSB0byBlbGltaW5hdGUgc2lnbmlmaWNhbnQgDQpwb3J0aW9uIG9mIHRoZSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMuIEkgZGlkIG5vdCB1c2UgdGhlIExvZ0ZDIHRvIA0KZGlzdGluZ3Vpc2ggYmV0d2VlbiBFTVQgR0xJMiB2cyBub24tRU1UIEdMSTIsIGJlY2F1c2UgYWxsIG9mIGxvZ0ZDIHZhbHVlcyBhcmUNCm5lZ2F0aXZlLiBUaGlzIGluZGljYXRlcyB0aGVyZSBpcyBhbHdheXMgdXAgcmVndWxhdGlvbiBhZnRlciB0aGUgRG94IHRyZWF0bWVudA0KYW5kIEdMSTIgZXhwcmVzc2lvbiBpcyBhbHdheXMgaGlnaGVyIHRoYW4gdGhlIGNvbnRyb2wuIFByZXR0eSBoaWdoIGNvbmZpZGVuY2UuDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KcWxmX3RvcGhpdHNfd2l0aGduIDwtIG1lcmdlKEdMSTJfZXhwWywxOjFdLCBxbGZfdG9wX2hpdHMsIGJ5Lnk9MCxieS54PTEsYWxsLnk9VFJVRSkNCg0KY29sbmFtZXMocWxmX3RvcGhpdHNfd2l0aGduKSA8LSBjKCJHZW5lX3N5bWJvbCIsICJsb2dGQyIsICJsb2dDUE0iLCJGIiwgIlBWYWx1ZSIsICJGRFIiKQ0KDQpxbGZfdG9waGl0c193aXRoZ25bLCJsb2dhcml0aG1pYyJdIDwtICgtbG9nKHFsZl90b3BoaXRzX3dpdGhnbiRQVmFsdWUpKQ0KcWxmX3RvcGhpdHNfd2l0aGduIDwtIHFsZl90b3BoaXRzX3dpdGhnbltvcmRlcihxbGZfdG9waGl0c193aXRoZ24kR2VuZV9zeW1ib2wpLF0NCg0KR0xJMl9lbXRfR2VuZXMgPC0gcWxmX3RvcGhpdHNfd2l0aGduJEdlbmVfc3ltYm9sW3doaWNoKHFsZl90b3BoaXRzX3dpdGhnbiRQVmFsdWUgPCAwLjAwMDUNCiAgICAgICAgICAgICAgICAmIHFsZl90b3BoaXRzX3dpdGhnbiRsb2dGQyA8IDApXQ0KR0xJMl9ub25fZW10Z2VuZXMgPC0gcWxmX3RvcGhpdHNfd2l0aGduJEdlbmVfc3ltYm9sW3doaWNoKHFsZl90b3BoaXRzX3dpdGhnbiRQVmFsdWUgPT0gMSldDQoNCndyaXRlLnRhYmxlKHg9R0xJMl9lbXRfR2VuZXMsIGZpbGUgPSBmaWxlLnBhdGgoZ2V0d2QoKSwiZGF0YSIsIkdMSTJfZW10X0dlbmVzLnR4dCIpLA0KICAgICAgICAgICAgIHNlcCA9ICIvIiwgcm93Lm5hbWVzID0gRkFMU0UsIGNvbC5uYW1lcyA9IEZBTFNFLCBxdW90ZSA9IEZBTFNFKQ0Kd3JpdGUudGFibGUoeD1HTEkyX25vbl9lbXRnZW5lcywgZmlsZSA9IGZpbGUucGF0aChnZXR3ZCgpLCJkYXRhIiwiR0xJMl9ub25fZW10Z2VuZXMudHh0IiksDQogICAgICAgICAgICAgICAgICAgc2VwID0gIi8iLCByb3cubmFtZXMgPSBGQUxTRSwgY29sLm5hbWVzID0gRkFMU0UsIHF1b3RlID0gRkFMU0UpDQp3cml0ZS50YWJsZSh4PWRhdGEuZnJhbWUoZ2VuZW5hbWU9cWxmX3RvcGhpdHNfd2l0aGduJEdlbmVfc3ltYm9sWzE4Om5yb3cocWxmX3RvcGhpdHNfd2l0aGduKV0pLGZpbGU9ZmlsZS5wYXRoKCJkYXRhIiwicmFua2VkX2dlbmVsaXN0LnJuayIpLHNlcCA9ICIvIiwNCiAgIHJvdy5uYW1lcyA9IEZBTFNFLGNvbC5uYW1lcyA9IEZBTFNFLHF1b3RlID0gRkFMU0UpDQpgYGANCiMjIyBQYXJ0IDE2OiBHUHJvZmlsZXIgZm9yIFVwcmVndWxhdGlvbiBhbmQgRG93bnJlZ3VsYXRpb24gcGF0aHdheSBhbmFseXNpcw0KVGhlIEdQcm9maWxlciBhbmFseXNpcyBpbmNsdWRlcyBCSCBjb3JyZWN0aW9uIG1ldGhvZHMgKEZEUikuIEkgc3RpY2tlZCB1c2luZyB0aGUgc2FtZSBtZXRob2QgYmVjYXVzZSBJIHVzZWQgdGhlIHNhbWUgdHlwZSBvZiBtZXRob2Qgb24gbXkgcHJldmlvdXMgYW5hbHlzaXMgb24gRkRSIHBvcnRpb24uIEZvciBib3RoIHVwcmVndWFsdGVkIGFuZCB0aGUgZG93bnJlZ3VsYXRlZCBnZW5lcyBJIGhhdmUgdXNlZCBHTzpCUCAoMjAyMi0xMi0wNCksIFJlYWN0b21lLCBhbmQgV2lraVBhdGh3YXlzKCBmb3IgYW5ub3RhdGlvbi4gVGhlc2UgYW5ub3RhdGlvbnMgYWxsb3dzIGZvciBiZXR0ZXIgYXNlc3NtZW50IG9mIG15IFVwcmVndWFsdGVkIGdlbmVzIGluIHRlcm1zIG9mIGRlZmluaW5nIHRoZSBiaW9sb2dpYyBwYXRod2F5cyB0aGV5IGFyZSBpbnZvdmxlZCBpbi4NCg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NClVwcmVndWxhdGVkX2dlbmVzIDwtIHJlYWQudGFibGUoZmlsZT1maWxlLnBhdGgoZ2V0d2QoKSwiZGF0YSIgLCJHTEkyX2VtdF9HZW5lcy50eHQiKSxoZWFkZXIgPSBUUlVFLCBzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UsIGNoZWNrLm5hbWVzID0gRkFMU0UpDQpVcHJlZ3VsYXRlZF9nZW5lcyA8LSBVcHJlZ3VsYXRlZF9nZW5lc1s0Om5yb3coVXByZWd1bGF0ZWRfZ2VuZXMpLF0NClVwcmVndWxhdGVkX0dwcm9maWxlcl92YWxpZGF0ZWQgPC0gZ3Byb2ZpbGVyMjo6Z29zdChxdWVyeSA9IFVwcmVndWxhdGVkX2dlbmVzLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2FwaWVucyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVfaWVhID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VzID0gYygiR086QlAiLCAiUkVBQyIsICJXUCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvcnJlY3Rpb25fbWV0aG9kID0gImZkciIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JkZXJlZF9xdWVyID0gRkFMU0UsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgKQ0KYGBgDQojIyMgQ29udGludWluZyBBbmFseXNpcw0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCkRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gcmVhZC50YWJsZShmaWxlPWZpbGUucGF0aChnZXR3ZCgpLCJkYXRhIiAsIkdMSTJfbm9uX2VtdGdlbmVzLnR4dCIpLGhlYWRlciA9IFRSVUUsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSwgY2hlY2submFtZXMgPSBGQUxTRSkNCkRvd25yZWd1bGF0ZWRfZ2VuZXMgPC0gRG93bnJlZ3VsYXRlZF9nZW5lc1sxMzpucm93KERvd25yZWd1bGF0ZWRfZ2VuZXMpLF0NCkRvd25yZWd1bGF0ZWRfR3Byb2ZpbGVyX3ZhbGlkYXRlZCA8LSBncHJvZmlsZXIyOjpnb3N0KHF1ZXJ5ID0gRG93bnJlZ3VsYXRlZF9nZW5lcywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2FwaWVucyIsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVfaWVhID0gVFJVRSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0aW9uX21ldGhvZCA9ICJmZHIiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG9yZGVyZWRfcXVlciA9IEZBTFNFLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNvdXJjZSA9IGMoIkdPOkJQIiwgIlJFQUMiLCAiV1AiKSkNCmBgYA0KIyMjIFBhcnQgMTc6IFN1YnNldHRpbmcgdGhlIEdwcm9maWxlciBkb3ducmVndWxhdGVkIGFuZCB1cHJlZ3VhbHRlZCBnZW5lcw0KQWZ0ZXIgc3Vic2V0dGluZyBJIGRvIGhhdmUgNzcxIGdlbmVzIHRoYXQgYXJlIGRvd24gcmVndWxhdGVkLiBEb3duIHJlZ3VhbHRlZCBnZW5lcyBhcmUgaW52b3ZsZWQgaW4gY29tbW9uIGJpb2xvZ2ljYWwgcGF0aHdheXMgdGhhdCBhcmUgbm90IGludm9sdmVkIGluIGNhbmNlcm91cyBhY3Rpdml0aWVzLg0KYGBge3IgbWVzc2FnZT1GQUxTRX0NCkRvd25yZWd1bGF0ZWRfZ2VuZXNfZmlsdGVyZWQgPC0gZGF0YS5mcmFtZSgNCiAgdGVybV9uYW1lID0gRG93bnJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkJHJlc3VsdCR0ZXJtX25hbWVbRG93bnJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkJHJlc3VsdCR0ZXJtX3NpemUgPCAyMDAgJiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBEb3ducmVndWxhdGVkX0dwcm9maWxlcl92YWxpZGF0ZWQkcmVzdWx0JHRlcm1fc2l6ZSA+IDFdLA0KICAgdGVybV9pZCAgPSBEb3ducmVndWxhdGVkX0dwcm9maWxlcl92YWxpZGF0ZWQkcmVzdWx0JHRlcm1faWRbRG93bnJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkJHJlc3VsdCR0ZXJtX3NpemUgPCAyMDAgJiANCiAgICAgICAgICAgICAgRG93bnJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkJHJlc3VsdCR0ZXJtX3NpemUgPiAxXSwNCiAgc291cmNlICA9IERvd25yZWd1bGF0ZWRfR3Byb2ZpbGVyX3ZhbGlkYXRlZCRyZXN1bHQkc291cmNlW0Rvd25yZWd1bGF0ZWRfR3Byb2ZpbGVyX3ZhbGlkYXRlZCRyZXN1bHQkdGVybV9zaXplIDwgMjAwICYNCiAgICAgICAgICAgICAgRG93bnJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkJHJlc3VsdCR0ZXJtX3NpemUgPiAxXQ0KKQ0KbGVuZ3RoKERvd25yZWd1bGF0ZWRfZ2VuZXNfZmlsdGVyZWQkdGVybV9uYW1lKQ0Ka25pdHI6OmthYmxlKERvd25yZWd1bGF0ZWRfZ2VuZXNfZmlsdGVyZWQkdGVybV9uYW1lWzE6NTBdLCBmb3JtYXQgPSAiaHRtbCIpDQpgYGANCiMjIyBGb3IgVXByZWd1bGF0aW9uDQpBZnRlciBzdWJzZXR0aW5nIEkgZG8gaGF2ZSAxMTI4IGdlbmVzIHRoYXQgYXJlIGRvd24gcmVndWxhdGVkLiBVcCByZWd1YWx0ZWQgZ2VuZXMgYXJlIG1vc3RseSBpbnZvdmxlZCBpbiBjYW5jZXIgYWN0aXZpdHkuIE1vc3Qgb2YgdGhlIHBhdGh3eWFzIGFyZSBxdWl0ZSBpbnZvdmxlZCBpbiBjYW5jZXJvdXMgYWN0aXZ0eS4gVGhlcmUgaXMgYSBsb3QgYXBvcHRvc2lzIGFuZCBwcm9ncmFtbWVkIGNlbGwgZGVhdGggYWN0aXZpdGllcy4NCmBgYHtyIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFfQ0KVXByZWd1bGF0ZWRfZ2VuZXNfZmlsdGVyZWQgPC0gZGF0YS5mcmFtZSgNCiAgdGVybV9uYW1lID0gVXByZWd1bGF0ZWRfR3Byb2ZpbGVyX3ZhbGlkYXRlZCRyZXN1bHQkdGVybV9uYW1lW1VwcmVndWxhdGVkX0dwcm9maWxlcl92YWxpZGF0ZWQkcmVzdWx0JHRlcm1fc2l6ZSA8IDIwMCAmICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFVwcmVndWxhdGVkX0dwcm9maWxlcl92YWxpZGF0ZWQkcmVzdWx0JHRlcm1fc2l6ZSA+IDFdLA0KICAgdGVybV9pZCAgPSBVcHJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkJHJlc3VsdCR0ZXJtX2lkW1VwcmVndWxhdGVkX0dwcm9maWxlcl92YWxpZGF0ZWQkcmVzdWx0JHRlcm1fc2l6ZSA8IDIwMCAmIA0KICAgICAgICAgICAgICBVcHJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkJHJlc3VsdCR0ZXJtX3NpemUgPiAxXSwNCiAgc291cmNlICA9IFVwcmVndWxhdGVkX0dwcm9maWxlcl92YWxpZGF0ZWQkcmVzdWx0JHNvdXJjZVtVcHJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkJHJlc3VsdCR0ZXJtX3NpemUgPCAyMDAgJg0KICAgICAgICAgICAgICBVcHJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkJHJlc3VsdCR0ZXJtX3NpemUgPiAxXQ0KKQ0KDQpsZW5ndGgoVXByZWd1bGF0ZWRfZ2VuZXNfZmlsdGVyZWQkdGVybV9uYW1lKQ0Ka25pdHI6OmthYmxlKFVwcmVndWxhdGVkX0dwcm9maWxlcl92YWxpZGF0ZWQkcmVzdWx0JHRlcm1fbmFtZVsxOjUwXSwgZm9ybWF0ID0gImh0bWwiKQ0KDQoNCmBgYA0KDQoNCiMjIyBQYXJ0IDE4OiBWaXN1YWxpemF0aW9ucyBvZiB0aGUgdXByZWd1YWx0ZWQgYW5kIHRoZSBkb3ducmVndWxhdGVkIGdlbmVzDQpgYGB7ciB9DQpncHJvZmlsZXIyOjpnb3N0cGxvdChVcHJlZ3VsYXRlZF9HcHJvZmlsZXJfdmFsaWRhdGVkKSAlPiUgcGxvdGx5OjpsYXlvdXQodGl0bGUgPSAiVXByZWd1bGF0ZWQgZ2VuZXMgIiwgZm9udCA9IGxpc3Qoc2l6ZSA9IDEwKSkNCg0KYGBgDQoNCiMjIyBDb250aW51aW5nDQpgYGB7ciB9DQpncHJvZmlsZXIyOjpnb3N0cGxvdChEb3ducmVndWxhdGVkX0dwcm9maWxlcl92YWxpZGF0ZWQpICU+JSBwbG90bHk6OmxheW91dCh0aXRsZSA9ICJEb3ducmVndWxhdGVkIGdlbmVzICIsIGZvbnQgPSBsaXN0KHNpemUgPSAxMCkpDQpgYGANCg0KIyMjIFBhcnQgMTk6IEdQcm9maWxlciBBbmFseXNlcyBmb3IgdGhlIG1lcmdlZCBkYXRhc2V0DQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KQ29tcGxldGVfR3Byb2ZpbGVyX0FuYWx5c2VzIDwtIGdwcm9maWxlcjI6Omdvc3QocXVlcnkgPSBtZXJnZWRfaGl0cyRHZW5lX3N5bWJvbCwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgb3JnYW5pc20gPSAiaHNhcGllbnMiLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBleGNsdWRlX2llYSA9IFRSVUUsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29ycmVjdGlvbl9tZXRob2QgPSAiZmRyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzb3VyY2VzID0gYygiR086QlAiLCAiUkVBQyIsICJXUCIpKQ0KDQpDb21wbGV0ZV9HcHJvZmlsZXJfQW5hbHlzZXNfZmlsdGVyZWQgPC0gZGF0YS5mcmFtZSh0ZXJtX25hbWUgPSBDb21wbGV0ZV9HcHJvZmlsZXJfQW5hbHlzZXMkcmVzdWx0JHRlcm1fbmFtZVtDb21wbGV0ZV9HcHJvZmlsZXJfQW5hbHlzZXMkcmVzdWx0JHRlcm1fc2l6ZSA8IDIwMCAmDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvbXBsZXRlX0dwcm9maWxlcl9BbmFseXNlcyRyZXN1bHQkdGVybV9zaXplID4gMV0sDQogIHRlcm1faWQgPSBDb21wbGV0ZV9HcHJvZmlsZXJfQW5hbHlzZXMkcmVzdWx0JHRlcm1faWRbQ29tcGxldGVfR3Byb2ZpbGVyX0FuYWx5c2VzJHJlc3VsdCR0ZXJtX3NpemUgPCAyMDAgJg0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIENvbXBsZXRlX0dwcm9maWxlcl9BbmFseXNlcyRyZXN1bHQkdGVybV9zaXplID4gMV0sDQogIHNvdXJjZSA9IENvbXBsZXRlX0dwcm9maWxlcl9BbmFseXNlcyRyZXN1bHQkc291cmNlW0NvbXBsZXRlX0dwcm9maWxlcl9BbmFseXNlcyRyZXN1bHQkdGVybV9zaXplIDwgMjAwICYNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgQ29tcGxldGVfR3Byb2ZpbGVyX0FuYWx5c2VzJHJlc3VsdCR0ZXJtX3NpemUgPiAxXSkNCg0KbGVuZ3RoKENvbXBsZXRlX0dwcm9maWxlcl9BbmFseXNlc19maWx0ZXJlZCR0ZXJtX25hbWUpDQprbml0cjo6a2FibGUoQ29tcGxldGVfR3Byb2ZpbGVyX0FuYWx5c2VzJHJlc3VsdCR0ZXJtX25hbWVbMToxMDBdLCBmb3JtYXQgPSAiaHRtbCIpDQpgYGANCiMjIyBDb250aW51aW5nDQpgYGB7ciBtZXNzYWdlPUZBTFNFfQ0KZ3Byb2ZpbGVyMjo6Z29zdHBsb3QoQ29tcGxldGVfR3Byb2ZpbGVyX0FuYWx5c2VzKSAlPiUgcGxvdGx5OjpsYXlvdXQodGl0bGUgPSAiQ29tcGxldGUgcGxvdCBwbG90IiwgZm9udCA9IGxpc3Qoc2l6ZSA9IDEwKSkNCmBgYA0KDQojIyMgUGFydCAyMDpJbnRlcnByZXRhdGlvbg0KDQojIyMjIERvIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIHJlc3VsdHMgc3VwcG9ydCBjb25jbHVzaW9ucyBvciBtZWNoYW5pc20gZGlzY3Vzc2VkIGluIHRoZSBvcmlnaW5hbCBwYXBlciA/IDxicj4NCg0KWWVzIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIHJlc3VsdHMgd2UgZmluZCBpcyBjb3JyZWxhdGVkIHRvIHRoZSBjb25jbHVzaW9uIHRoZQ0KYXV0aG9ycyBtYWtlLiBUaGV5IGNvbmNsdWRlIHRoYXQgZ2VuZXMgaGF2aW5nIGhpZ2hlciBHTEkyIGV4cHJlc3Npb24sIG1vcmUgDQpkaWZmZXJlbnRpYWxseSBleHByZXNzZWQsIGFyZSBtb3JlIHBvc3NpYmxlIHRvIGJlIEVNVCBnZW5lcy4gQWRkaXRpb25hbGx5LCB3ZSANCmZvdW5kIHRoZXJlIGlzIGFsd2F5cyBoaWdoZXIgZXhwcmVzc2lvbiBvbiBHTEkyIHRyZWF0bWVudHMgZ2l2ZW4gdGhpcyBpcyBhIHN0cm9uZw0Kb25jb2dlbmUgYWN0aW5nIGluIGJhc2FsLXN1Yi10eXBlIHN3aXRjaGluZyB0cmlnZ2VyaW5nIEVNVCBzd2l0Y2hpbmcuIEFzIGl0IGlzIG9idmlvdXMgZnJvbSB0aGUgdmlzdWFsaXphdGlvbiB0aGUgdXByZWd1YWx0ZWQgZ2VuZXMgYXJlIG1vcmUgY2x1c3RlcmVkIGFuZCBhcmUgbXVjaCBtb3JlIGluIHRoZSBkb3ducmVndWFsdGVkIGdlbmVzIFRoaXMgc3VwcG9ydHMgdGhlIGh5cG90aGVzaXMgb2YgYXV0aG9ycywgY29uY2x1ZGluZyB0aGUgRU1UIGdlbmVzIHRvIGJlIGhpZ2hlciBleHByZXNzaW9uIHRoYW4gdGhhdCBvZiB0aGUgZG93bnJlZ3VhbHRlZCBnZW5lcy4NCg0KIyMjIyBDYW4geW91IGZpbmQgZXZpZGVuY2UsIGkuZS4gcHVibGljYXRpb25zLCB0byBzdXBwb3J0IHNvbWUgb2YgdGhlIHJlc3VsdHMgdGhhdCB5b3Ugc2VlLiBIb3cgZG9lcyB0aGlzIGV2aWRlbmNlIHN1cHBvcnQgeW91ciByZXN1bHRzID8gPGJyPg0KDQpUaGUgcGFwZXIgKFBhc2NhIGRpIE1hZ2xpYW5vIGV0IGFsLiwyMDA2KSBoYXMgYWxyZWFkeSBpbmRpY2F0ZWQgaW5jcmVhc2UgDQpleHByZXNzaW9uIG9mIEdMSTIgY2FuIGxlYWQgdG8gU0hIIGdlbmUgcmVkdWN0aW9uLiBUaGlzIGdlbmUgaGFzIGJlZW4ga25vd24gdG8gDQpiZSBhbiBvbmNvZ2VuZSBhc3NvY2lhdGVkIHdpdGggYmFzYWwtc3ViLXR5cGUgc3dpdGNoaW5nIGluIFBEQUMuIFRoZXkgYWN0aXZhdGUgDQpHTEkyIGNvbnN0YW50bHkgd2hpY2ggaGFzIHRoZSBzYW1lIGV4cGVjdGVkIG91dGNvbWUgaW4gb3VyIGRhdGEgc2V0IGhhdmluZw0KR0xJMiBleHByZXNzaW5nIHZlY3RvcnMgd2l0aCBjb25zdGFudCBEb3ggdHJlYXRtZW50LiBJbiBjb25jbHVzaW9uIHRoZXNlIHR3bw0KcGFwZXIgZmluZGluZ3MgY29ycmVsYXRlIGVhY2ggb3RoZXIuIFRoZXkgc2hvdyB0aGF0IHRoZSBFTVQgZ2VuZXMgdG8gYmUgYWJ1bmRhbnQgaW4gdGhlaXIgYmlvbG9naWNhbCBmdW5jdGlvbnMgYW5kIHRoZWlyIHBhdGh3YXkgaW52b3ZsZW1lbnQuDQoNCiMjIFJlZmVyZW5jZXMNCg==